use std::cmp::Ordering;

use axum::Json;
use chrono::{ Duration, Local, MappedLocalTime, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc };
use sea_orm::prelude::DateTimeUtc;
use serde_json::Value;

use crate::code;
// 重新格式化 tz 时间
// pub fn date_time_utc(str:&str) -> Result<DateTime<Utc>, &str> {
//     match NaiveDateTime::parse_from_str(str, "%Y-%m-%dT%H:%M:%SZ") {
//         Ok(f) => Ok(f.and_utc()),
//         _ => Err(" 必须是日期字符串 yy-mm-dd hh:mm:ss")
//      }
// }

// 将字符串转为 y-m-d h:m:s
pub fn date_time(str:&str) -> Result<NaiveDateTime, Json<Value>> {
    if let Ok(f) = NaiveDateTime::parse_from_str(str, "%Y-%m-%d %H:%M:%S") {
        Ok(f)
    }else{
        Err(code::err_("必须是日期字符串 yy-mm-dd hh:mm:ss"))
    }
}
pub fn date_ymd_hm(str:&str) -> Result<NaiveDateTime, Json<Value>> {
    if let Ok(f) = NaiveDateTime::parse_from_str(str, "%Y-%m-%d %H:%M") {
        Ok(f)
    }else{
        Err(code::err_("必须是日期字符串 yy-mm-dd hh:mm"))
    }
}
pub fn date_time_utc(str:&str) -> Result<DateTimeUtc, Json<Value>> {
    if let Ok(f) = NaiveDateTime::parse_from_str(str, "%Y-%m-%d %H:%M:%S"){
        Ok(f.and_utc().with_timezone(&Utc))
    }else{
        Err(code::err_("必须是日期字符串 yy-mm-dd hh:mm:ss"))
    }
}
pub fn date_utc(str:&str) -> Result<DateTimeUtc, Json<Value>> {
    if let Ok(f) = NaiveDate::parse_from_str(str, "%Y-%m-%d"){
        Ok(f.and_hms_opt(0, 0, 0).unwrap_or_default().and_utc().with_timezone(&Utc))
    }else{
        Err(code::err_("必须是日期字符串 yy-mm-dd"))
    }
}
// 将字符串转为 y-m-d
pub fn date(str:&str) -> Result<NaiveDate, Json<Value>> {
    if let Ok(f) = NaiveDate::parse_from_str(str, "%Y-%m-%d"){
        Ok(f)
    }else {
        Err(code::err_("必须是日期字符串 yy-mm-dd"))
    }
}
// 将字符串转为 h:m:s
pub fn time(str:&str) -> Result<NaiveTime, Json<Value>> {
    if let Ok(f) = NaiveTime::parse_from_str(str, "%H:%M:%S"){
        Ok(f)
    }else{
        Err(code::err_("必须是时间字符串 hh:mm:ss"))
    }
}
// 将字符串转为 h:m
pub fn time_hm(str:&str) -> Result<NaiveTime, Json<Value>> {
    match NaiveTime::parse_from_str(str, "%H:%M") {
        Ok(f) => Ok(f),
        _ => Err(code::err_("必须是时间字符串 hh:mm"))
    }
}
// 格式化 Datetime
pub fn date_format_from_millis(milis:i64) -> Result<String, Json<Value>> {
    match Local.timestamp_millis_opt(milis) {
        MappedLocalTime::Single(dt) => {
            Ok(dt.naive_local().format("%Y-%m-%d %H:%M:%S").to_string( ))
        },
        _ => Err(code::err_("必须是时间戳数字"))
    }
}
// 获取当前时间戳
pub fn now()-> i64 {
    let time = Local::now( );
    time.timestamp()
}
// 获取当前格式化时间
pub fn now_format(index:usize)-> String {
    let vec = vec![
        "%Y-%m-%d",
        "%Y-%m-%d %H:%M:%S", 
        "%H:%M:%S", 
        "%Y%m%d%H%M%S",
        "%Y%m%d"
    ];
    Local::now( ).naive_local().format(vec[index]).to_string( )
}
// 数据库保存当前日期
pub fn now_date() -> Result<NaiveDate, Json<Value>>{
    match date( &now_format(0) ) {
        Ok(f) => Ok(f),
        Err(e) => Err(e)
    }
}
pub fn now_date_time() -> Result<NaiveDateTime, Json<Value>>{
    match date_time( &now_format(1) ) {
        Ok(f) => Ok(f),
        Err(e) => Err(e)
    }
}
pub fn now_date_time_utc() -> DateTimeUtc { Utc::now() }
pub fn date_add_year(time:NaiveDate, year:i64) -> NaiveDate{ time + Duration::days( 365 * year ) }
pub fn date_add_month(time:NaiveDate, month:i64) -> NaiveDate{ time + Duration::days( 30 * month ) }
pub fn date_add_days(time:NaiveDate, day:i64) -> NaiveDate{ time + Duration::days( day ) }

pub fn date_time_add_year(time:NaiveDateTime, year:i64) -> NaiveDateTime{ time + Duration::days( 365 * year ) }
pub fn date_time_add_month(time:NaiveDateTime, month:i64) -> NaiveDateTime{ time + Duration::days( 30 * month ) }
pub fn date_time_add_days(time:NaiveDateTime, day:i64) -> NaiveDateTime{ time + Duration::days( day ) }
pub fn date_time_add_hours(time:NaiveDateTime, hours:i64) -> NaiveDateTime{ time + Duration::hours( hours ) }
pub fn date_time_add_minutes(time:NaiveDateTime, minutes:i64) -> NaiveDateTime{ time + Duration::minutes( minutes ) }
pub fn date_time_add_seconds(time:NaiveDateTime, seconds:i64) -> NaiveDateTime{ time + Duration::seconds( seconds ) }
// 以年计算使用时长
pub fn expire_year_date(year:i64) -> NaiveDate {
    let now = Local::now( );
    let expr = now + Duration::days( 365 * year );
    expr.date_naive()
}
// 以年计算续费时长
pub fn expire_year_exp_date(year:i64, exp:NaiveDate) -> NaiveDate {
    let now = Local::now( );
    if exp.cmp(&now.date_naive()).eq(&Ordering::Greater) {
        exp + Duration::days( 365 * year )
    }else{
        let expr = now + Duration::days( 365 * year );
        expr.date_naive()
    }
}
// 微信计算过期时间
pub fn wx_expire_minutes(minutes:i64) -> String {
    let now = Utc::now();
    let expr = now + Duration::minutes( minutes );
    expr.with_timezone(&Local).format("%Y-%m-%dT%H:%M:%S+08:00").to_string()
}
// 最近多少天
pub fn latest_date(day:i64) -> NaiveDate {
    let now = Local::now( );
    let expr = now - Duration::days( day );
    expr.date_naive()
}